package player_event

import (
	"errors"
	"fmt"
	"game_server/model"
)

type (
	onLoginEvent struct {
	}
	loginCallback = func(player *model.Player, isFirst bool)
)

var OnLogin = new(onLoginEvent)

func (event *onLoginEvent) Verify(callback interface{}) (err error) {
	if _, ok := callback.(loginCallback); !ok {
		err = errors.New("not on login event callback function")
	}

	return
}

func (event *onLoginEvent) Call(callback interface{}, args []interface{}) (err error) {
	const ArgsCount = 2
	if len(args) < ArgsCount {
		err = fmt.Errorf("on login event callback need %d arg", ArgsCount)
		return
	}

	call := callback.(loginCallback)
	i := 0
	player := args[i].(*model.Player)
	i++
	isFirst := args[i].(bool)
	i++

	call(player, isFirst)

	return
}

type (
	onLogoutEvent struct {
	}
	logoutCallback = func(player *model.Player)
)

var OnLogout = new(onLogoutEvent)

func (event *onLogoutEvent) Verify(callback interface{}) (err error) {
	if _, ok := callback.(logoutCallback); !ok {
		err = errors.New("not on logout event callback function")
	}

	return
}

func (event *onLogoutEvent) Call(callback interface{}, args []interface{}) (err error) {
	const ArgsCount = 1
	if len(args) < ArgsCount {
		err = fmt.Errorf("on logout event callback need %d arg", ArgsCount)
		return
	}

	call := callback.(logoutCallback)
	i := 0
	player := args[i].(*model.Player)
	i++

	call(player)

	return
}

type (
	onExitEvent struct {
	}
	exitCallback = func(player *model.Player)
)

var OnExit = new(onExitEvent)

func (event *onExitEvent) Verify(callback interface{}) (err error) {
	if _, ok := callback.(exitCallback); !ok {
		err = errors.New("not on exit event callback function")
	}

	return
}

func (event *onExitEvent) Call(callback interface{}, args []interface{}) (err error) {
	const ArgsCount = 1
	if len(args) < ArgsCount {
		err = fmt.Errorf("on exit event callback need %d arg", ArgsCount)
		return
	}

	call := callback.(exitCallback)
	i := 0
	player := args[i].(*model.Player)
	i++

	call(player)

	return
}

type (
	onLevelChangeEvent struct {
	}
	levelChangeCallback = func(player *model.Player, newLevel uint16, oldLevel uint16)
)

var OnLevelChange = new(onLevelChangeEvent)

func (event *onLevelChangeEvent) Verify(callback interface{}) (err error) {
	if _, ok := callback.(levelChangeCallback); !ok {
		err = errors.New("not on level change event callback function")
	}

	return
}

func (event *onLevelChangeEvent) Call(callback interface{}, args []interface{}) (err error) {
	const ArgsCount = 3
	if len(args) < ArgsCount {
		err = fmt.Errorf("on level change event callback need %d arg", ArgsCount)
		return
	}

	call := callback.(levelChangeCallback)
	i := 0
	player := args[i].(*model.Player)
	i++
	newLevel := args[i].(uint16)
	i++
	oldLevel := args[i].(uint16)
	i++

	call(player, newLevel, oldLevel)

	return
}
